/*
 * Copyright (C) 2005 - 2013 MaNGOS <http://www.getmangos.com/>
 *
 * Copyright (C) 2008 - 2013 Trinity <http://www.trinitycore.org/>
 *
 * Copyright (C) 2006 - 2013 ScriptDev2 <http://www.scriptdev2.com/>
 *
 * Copyright (C) 2010 - 2013 ProjectSkyfire <http://www.projectskyfire.org/>
 *
 * Copyright (C) 2011 - 2013 ArkCORE <http://www.arkania.net/>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/* ScriptData
 SDName: Dustwallow_Marsh
 SD%Complete: 95
 SDComment: Quest support: 11180, 558, 11126, 11142, 11180. Vendor Nat Pagle
 SDCategory: Dustwallow Marsh
 EndScriptData */

/* ContentData
 mobs_risen_husk_spirit
 npc_restless_apparition
 npc_deserter_agitator
 npc_lady_jaina_proudmoore
 npc_nat_pagle
 npc_private_hendel
 npc_cassa_crimsonwing - handled by npc_taxi
 EndContentData */

#include "ScriptPCH.h"
#include "ScriptedEscortAI.h"

/*######
 ## mobs_risen_husk_spirit
 ######*/

enum eHuskSpirit {
    QUEST_WHATS_HAUNTING_WITCH_HILL = 11180,

    SPELL_SUMMON_RESTLESS_APPARITION = 42511, SPELL_CONSUME_FLESH = 37933, //Risen Husk
    SPELL_INTANGIBLE_PRESENCE = 43127, //Risen Spirit

    NPC_RISEN_HUSK = 23555,
    NPC_RISEN_SPIRIT = 23554,
    NPC_RESTLESS_APPARITION = 23861
};

class mobs_risen_husk_spirit: public CreatureScript {
public:
    mobs_risen_husk_spirit() :
            CreatureScript("mobs_risen_husk_spirit") {
    }

    CreatureAI* GetAI(Creature* pCreature) const {
        return new mobs_risen_husk_spiritAI(pCreature);
    }

    struct mobs_risen_husk_spiritAI: public ScriptedAI {
        mobs_risen_husk_spiritAI(Creature *c) :
                ScriptedAI(c) {
        }

        uint32 m_uiConsumeFlesh_Timer;
        uint32 m_uiIntangiblePresence_Timer;

        void Reset() {
            m_uiConsumeFlesh_Timer = 10000;
            m_uiIntangiblePresence_Timer = 5000;
        }

        void UpdateAI(const uint32 uiDiff) {
            if (!UpdateVictim())
                return;

            if (m_uiConsumeFlesh_Timer <= uiDiff) {
                if (me->GetEntry() == NPC_RISEN_HUSK)
                    DoCast(me->getVictim(), SPELL_CONSUME_FLESH);

                m_uiConsumeFlesh_Timer = 15000;
            } else
                m_uiConsumeFlesh_Timer -= uiDiff;

            if (m_uiIntangiblePresence_Timer <= uiDiff) {
                if (me->GetEntry() == NPC_RISEN_SPIRIT)
                    DoCast(me->getVictim(), SPELL_INTANGIBLE_PRESENCE);

                m_uiIntangiblePresence_Timer = 20000;
            } else
                m_uiIntangiblePresence_Timer -= uiDiff;

            DoMeleeAttackIfReady();
        }

        void JustDied(Unit* pKiller) {
            if (pKiller->GetTypeId() == TYPEID_PLAYER)
                if (CAST_PLR(pKiller)->GetQuestStatus(
                        QUEST_WHATS_HAUNTING_WITCH_HILL)
                        == QUEST_STATUS_INCOMPLETE) {
                    DoCast(pKiller, SPELL_SUMMON_RESTLESS_APPARITION, true);
                    CAST_PLR(pKiller)->KilledMonsterCredit(
                            NPC_RESTLESS_APPARITION, 0);
                }
        }
    };
};

/*######
 ## npc_restless_apparition
 ######*/

enum eRestlessApparition {
    SAY_RESTLESS_1 = -1000469,
    SAY_RESTLESS_2 = -1000470,
    SAY_RESTLESS_3 = -1000471
};

class npc_restless_apparition: public CreatureScript {
public:
    npc_restless_apparition() :
            CreatureScript("npc_restless_apparition") {
    }

    CreatureAI* GetAI(Creature* pCreature) const {
        return new npc_restless_apparitionAI(pCreature);
    }

    struct npc_restless_apparitionAI: public ScriptedAI {
        npc_restless_apparitionAI(Creature* pCreature) :
                ScriptedAI(pCreature) {
        }

        void Reset() {
            DoScriptText(RAND(SAY_RESTLESS_1, SAY_RESTLESS_2, SAY_RESTLESS_3),
                    me);
        }
    };
};

/*######
 ## npc_deserter_agitator
 ######*/

enum eDeserter {
    QUEST_TRAITORS_AMONG_US = 11126, NPC_THERAMORE_DESERTER = 23602,
};

const Position DeserterDisappearPos =
        { -3609.03f, -4332.91f, 9.39354f, 3.73862f };

#define GOSSIP_ITEM_DESERTER "Your propaganda wont`t work on me. Spout your treasonous filth elsewhere traitor!"

class npc_deserter_agitator: public CreatureScript {
public:
    npc_deserter_agitator() :
            CreatureScript("npc_deserter_agitator") {
    }

    bool OnGossipHello(Player* pPlayer, Creature* pCreature) {
        if (pPlayer->GetQuestStatus(QUEST_TRAITORS_AMONG_US)
                == QUEST_STATUS_INCOMPLETE)
            pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DESERTER, GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO);

        pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());

        return true;
    }

    bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 uiSender,
            uint32 uiAction) {
        pPlayer->PlayerTalkClass->ClearMenus();

        if (uiAction == GOSSIP_SENDER_INFO) {
            pPlayer->CLOSE_GOSSIP_MENU();
            switch (urand(0, 1)) {
            case 0:
                pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
                pCreature->setFaction(14);
                pCreature->AI()->AttackStart(pPlayer);
                break;
            case 1:
                pPlayer->KilledMonsterCredit(NPC_THERAMORE_DESERTER, 0);
                pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
                pCreature->SetSpeed(MOVE_RUN, pCreature->GetSpeedRate(MOVE_RUN),
                        true);
                pCreature->setFaction(35);
                pCreature->SetFlag(
                        UNIT_FIELD_FLAGS,
                        UNIT_FLAG_OOC_NOT_ATTACKABLE
                                | UNIT_FLAG_NON_ATTACKABLE);
                pCreature->SetReactState(REACT_PASSIVE);
                pCreature->GetMotionMaster()->MovePoint(1,
                        DeserterDisappearPos);
                break;
            }
        }

        return true;
    }

    CreatureAI* GetAI(Creature* pCreature) const {
        return new npc_deserter_agitatorAI(pCreature);
    }

    struct npc_deserter_agitatorAI: public ScriptedAI {
        npc_deserter_agitatorAI(Creature* pCreature) :
                ScriptedAI(pCreature) {
        }

        void Reset() {
            me->RestoreFaction();
            me->RemoveFlag(UNIT_FIELD_FLAGS,
                    UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_NON_ATTACKABLE);
            me->SetReactState(REACT_AGGRESSIVE);
            me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
        }

        void MovementInform(uint32 uiType, uint32 uiId) {
            if (uiType != POINT_MOTION_TYPE)
                return;

            if (uiId == 1)
                me->DisappearAndDie();
        }
    };
};

/*######
 ## npc_deserter_agitator
 ######*/

enum eTheramoreGuard {
    SAY_QUEST1 = -1000641,
    SAY_QUEST2 = -1000642,
    SAY_QUEST3 = -1000643,
    SAY_QUEST4 = -1000644,
    SAY_QUEST5 = -1000645,
    SAY_QUEST6 = -1000646,
    SAY_QUEST7 = -1000647,
    SAY_QUEST8 = -1000648,
    SAY_QUEST9 = -1000649,

    QUEST_DISCREDITING_THE_DESERTERS = 11133,

    NPC_THERAMORE_GUARD = 4979,

    SPELL_DOCTORED_LEAFLET = 42725,
    SPELL_PROPAGANDIZED = 42246,
};

#define GOSSIP_ITEM_THERAMORE_GUARD "You look like an intelligent person. Why don't you read one of these leaflets and give it some thought?"

class npc_theramore_guard: public CreatureScript {
public:
    npc_theramore_guard() :
            CreatureScript("npc_theramore_guard") {
    }

    bool OnGossipHello(Player* pPlayer, Creature* pCreature) {
        if (pPlayer->GetQuestStatus(QUEST_DISCREDITING_THE_DESERTERS)
                == QUEST_STATUS_INCOMPLETE)
            pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_THERAMORE_GUARD, GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO);

        pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());

        return true;
    }

    bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 uiSender,
            uint32 uiAction) {
        pPlayer->PlayerTalkClass->ClearMenus();

        if (uiAction == GOSSIP_SENDER_INFO) {
            pPlayer->CLOSE_GOSSIP_MENU();
            pPlayer->KilledMonsterCredit(NPC_THERAMORE_GUARD, 0);
            DoScriptText(SAY_QUEST1, pCreature);
            pCreature->CastSpell(pCreature, SPELL_DOCTORED_LEAFLET, false);
            pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
            CAST_AI(npc_theramore_guard::npc_theramore_guardAI, pCreature->AI())->uiYellTimer =
                    4000;
            CAST_AI(npc_theramore_guard::npc_theramore_guardAI, pCreature->AI())->bYellTimer =
                    true;
        }

        return true;
    }

    CreatureAI *GetAI(Creature *pCreature) const {
        return new npc_theramore_guardAI(pCreature);
    }

    struct npc_theramore_guardAI: public ScriptedAI {
        npc_theramore_guardAI(Creature *pCreature) :
                ScriptedAI(pCreature) {
        }

        uint32 uiYellTimer;
        uint32 uiStep;
        bool bYellTimer;

        void Reset() {
            bYellTimer = false;
            uiStep = 0;
        }

        void UpdateAI(const uint32 uiDiff) {
            if (!me->HasAura(SPELL_PROPAGANDIZED))
                me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);

            if (bYellTimer && uiYellTimer <= uiDiff) {
                switch (uiStep) {
                case 0:
                    DoScriptText(
                            RAND(SAY_QUEST2, SAY_QUEST3, SAY_QUEST4, SAY_QUEST5,
                                    SAY_QUEST6), me);
                    uiYellTimer = 3000;
                    ++uiStep;
                    break;
                case 1:
                    DoScriptText(RAND(SAY_QUEST7, SAY_QUEST8, SAY_QUEST9), me);
                    me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH);
                    uiStep = 0;
                    bYellTimer = false;
                    break;
                }
            } else
                uiYellTimer -= uiDiff;
        }
    };
};

/*######
 ## npc_lady_jaina_proudmoore
 ######*/

enum eLadyJaina {
    QUEST_JAINAS_AUTOGRAPH = 558, SPELL_JAINAS_AUTOGRAPH = 23122
};

#define GOSSIP_ITEM_JAINA "I know this is rather silly but i have a young ward who is a bit shy and would like your autograph."

class npc_lady_jaina_proudmoore: public CreatureScript {
public:
    npc_lady_jaina_proudmoore() :
            CreatureScript("npc_lady_jaina_proudmoore") {
    }

    bool OnGossipSelect(Player* pPlayer, Creature* pCreature,
            uint32 /*uiSender*/, uint32 uiAction) {
        pPlayer->PlayerTalkClass->ClearMenus();
        if (uiAction == GOSSIP_SENDER_INFO) {
            pPlayer->SEND_GOSSIP_MENU(7012, pCreature->GetGUID());
            pPlayer->CastSpell(pPlayer, SPELL_JAINAS_AUTOGRAPH, false);
        }
        return true;
    }

    bool OnGossipHello(Player* pPlayer, Creature* pCreature) {
        if (pCreature->isQuestGiver())
            pPlayer->PrepareQuestMenu(pCreature->GetGUID());

        if (pPlayer->GetQuestStatus(QUEST_JAINAS_AUTOGRAPH)
                == QUEST_STATUS_INCOMPLETE)
            pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_JAINA, GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO);

        pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());

        return true;
    }
};

/*######
 ## npc_nat_pagle
 ######*/

enum eNatPagle {
    QUEST_NATS_MEASURING_TAPE = 8227
};

class npc_nat_pagle: public CreatureScript {
public:
    npc_nat_pagle() :
            CreatureScript("npc_nat_pagle") {
    }

    bool OnGossipSelect(Player* pPlayer, Creature* pCreature,
            uint32 /*uiSender*/, uint32 uiAction) {
        pPlayer->PlayerTalkClass->ClearMenus();
        if (uiAction == GOSSIP_ACTION_TRADE)
            pPlayer->SEND_VENDORLIST(pCreature->GetGUID());

        return true;
    }

    bool OnGossipHello(Player* pPlayer, Creature* pCreature) {
        if (pCreature->isQuestGiver())
            pPlayer->PrepareQuestMenu(pCreature->GetGUID());

        if (pCreature->isVendor()
                && pPlayer->GetQuestRewardStatus(QUEST_NATS_MEASURING_TAPE)) {
            pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
            pPlayer->SEND_GOSSIP_MENU(7640, pCreature->GetGUID());
        } else
            pPlayer->SEND_GOSSIP_MENU(7638, pCreature->GetGUID());

        return true;
    }
};

/*######
 ## npc_private_hendel
 ######*/

enum eHendel {
    // looks like all this text ids are wrong.
    SAY_PROGRESS_1_TER = -1000411, // signed for 3568
    SAY_PROGRESS_2_HEN = -1000412, // signed for 3568
    SAY_PROGRESS_3_TER = -1000413,
    SAY_PROGRESS_4_TER = -1000414,
    EMOTE_SURRENDER = -1000415,

    QUEST_MISSING_DIPLO_PT16 = 1324,
    FACTION_HOSTILE = 168, //guessed, may be different

    NPC_SENTRY = 5184, //helps hendel
    NPC_JAINA = 4968, //appears once hendel gives up
    NPC_TERVOSH = 4967
};

//TODO: develop this further, end event not created
class npc_private_hendel: public CreatureScript {
public:
    npc_private_hendel() :
            CreatureScript("npc_private_hendel") {
    }

    bool OnQuestAccept(Player* /*pPlayer*/, Creature* pCreature,
            const Quest* pQuest) {
        if (pQuest->GetQuestId() == QUEST_MISSING_DIPLO_PT16)
            pCreature->setFaction(FACTION_HOSTILE);

        return true;
    }

    CreatureAI* GetAI(Creature* pCreature) const {
        return new npc_private_hendelAI(pCreature);
    }

    struct npc_private_hendelAI: public ScriptedAI {
        npc_private_hendelAI(Creature* pCreature) :
                ScriptedAI(pCreature) {
        }

        void Reset() {
            me->RestoreFaction();
        }

        void AttackedBy(Unit* pAttacker) {
            if (me->getVictim())
                return;

            if (me->IsFriendlyTo(pAttacker))
                return;

            AttackStart(pAttacker);
        }

        void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) {
            if (uiDamage > me->GetHealth()
                    || me->HealthBelowPctDamaged(20, uiDamage)) {
                uiDamage = 0;

                if (Player* pPlayer = pDoneBy->GetCharmerOrOwnerPlayerOrPlayerItself())
                    pPlayer->GroupEventHappens(QUEST_MISSING_DIPLO_PT16, me);

                DoScriptText(EMOTE_SURRENDER, me);
                EnterEvadeMode();
            }
        }
    };
};

/*######
 ## npc_zelfrax
 ######*/

const Position MovePosition = { -2967.030f, -3872.1799f, 35.620f, 0.0f };

enum eZelfrax {
    SAY_ZELFRAX = -1000472, SAY_ZELFRAX_2 = -1000473
};

class npc_zelfrax: public CreatureScript {
public:
    npc_zelfrax() :
            CreatureScript("npc_zelfrax") {
    }

    CreatureAI* GetAI(Creature* pCreature) const {
        return new npc_zelfraxAI(pCreature);
    }

    struct npc_zelfraxAI: public ScriptedAI {
        npc_zelfraxAI(Creature* pCreature) :
                ScriptedAI(pCreature) {
            MoveToDock();
        }

        void AttackStart(Unit* pWho) {
            if (!pWho)
                return;

            if (me->Attack(pWho, true)) {
                me->SetInCombatWith(pWho);
                pWho->SetInCombatWith(me);

                if (IsCombatMovement())
                    me->GetMotionMaster()->MoveChase(pWho);
            }
        }

        void MovementInform(uint32 uiType, uint32 /*uiId*/) {
            if (uiType != POINT_MOTION_TYPE)
                return;

            me->SetHomePosition(me->GetPositionX(), me->GetPositionY(),
                    me->GetPositionZ(), me->GetOrientation());
            me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
            SetCombatMovement(true);

            if (me->isInCombat())
                if (Unit* pUnit = me->getVictim())
                    me->GetMotionMaster()->MoveChase(pUnit);
        }

        void MoveToDock() {
            SetCombatMovement(false);
            me->GetMotionMaster()->MovePoint(0, MovePosition);
            DoScriptText(SAY_ZELFRAX, me);
            DoScriptText(SAY_ZELFRAX_2, me);
        }

        void UpdateAI(uint32 const /*uiDiff*/) {
            if (!UpdateVictim())
                return;

            DoMeleeAttackIfReady();
        }
    };
};

/////////////////////
/// npc_stinky
/////////////////////

enum eStinky {
    QUEST_STINKYS_ESCAPE_H = 1270,
    QUEST_STINKYS_ESCAPE_A = 1222,
    SAY_QUEST_ACCEPTED = -1000507,
    SAY_STAY_1 = -1000508,
    SAY_STAY_2 = -1000509,
    SAY_STAY_3 = -1000510,
    SAY_STAY_4 = -1000511,
    SAY_STAY_5 = -1000512,
    SAY_STAY_6 = -1000513,
    SAY_QUEST_COMPLETE = -1000514,
    SAY_ATTACKED_1 = -1000515,
    EMOTE_DISAPPEAR = -1000516
};

class npc_stinky: public CreatureScript {
public:
    npc_stinky() :
            CreatureScript("npc_stinky") {
    }

    CreatureAI* GetAI(Creature* pCreature) const {
        return new npc_stinkyAI(pCreature);
    }

    bool OnQuestAccept(Player* pPlayer, Creature* pCreature,
            Quest const *quest) {
        if (quest->GetQuestId() == QUEST_STINKYS_ESCAPE_H
                || QUEST_STINKYS_ESCAPE_A) {
            if (npc_stinkyAI* pEscortAI = CAST_AI(npc_stinky::npc_stinkyAI, pCreature->AI())) {
                pCreature->setFaction(FACTION_ESCORT_N_NEUTRAL_ACTIVE);
                pCreature->SetStandState(UNIT_STAND_STATE_STAND);
                DoScriptText(SAY_QUEST_ACCEPTED, pCreature);
                pEscortAI->Start(false, false, pPlayer->GetGUID());
            }
        }
        return true;
    }

    struct npc_stinkyAI: public npc_escortAI {
        npc_stinkyAI(Creature* pCreature) :
                npc_escortAI(pCreature) {
        }

        void WaypointReached(uint32 i) {
            Player* pPlayer = GetPlayerForEscort();
            if (!pPlayer)
                return;

            switch (i) {
            case 7:
                DoScriptText(SAY_STAY_1, me, pPlayer);
                break;
            case 11:
                DoScriptText(SAY_STAY_2, me, pPlayer);
                break;
            case 25:
                DoScriptText(SAY_STAY_3, me, pPlayer);
                break;
            case 26:
                DoScriptText(SAY_STAY_4, me, pPlayer);
                break;
            case 27:
                DoScriptText(SAY_STAY_5, me, pPlayer);
                break;
            case 28:
                DoScriptText(SAY_STAY_6, me, pPlayer);
                me->SetStandState(UNIT_STAND_STATE_KNEEL);
                break;
            case 29:
                me->SetStandState(UNIT_STAND_STATE_STAND);
                break;
            case 37:
                DoScriptText(SAY_QUEST_COMPLETE, me, pPlayer);
                me->SetSpeed(MOVE_RUN, 1.2f, true);
                me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
                if (pPlayer && pPlayer->GetQuestStatus(QUEST_STINKYS_ESCAPE_H))
                    pPlayer->GroupEventHappens(QUEST_STINKYS_ESCAPE_H, me);
                if (pPlayer && pPlayer->GetQuestStatus(QUEST_STINKYS_ESCAPE_A))
                    pPlayer->GroupEventHappens(QUEST_STINKYS_ESCAPE_A, me);
                break;
            case 39:
                DoScriptText(EMOTE_DISAPPEAR, me);
                break;
            }
        }

        void EnterCombat(Unit* pWho) {
            DoScriptText(SAY_ATTACKED_1, me, pWho);
        }

        void Reset() {
        }

        void JustDied(Unit* /*pKiller*/) {
            Player* pPlayer = GetPlayerForEscort();
            if (HasEscortState(STATE_ESCORT_ESCORTING) && pPlayer) {
                if (pPlayer->GetQuestStatus(QUEST_STINKYS_ESCAPE_H))
                    pPlayer->FailQuest(QUEST_STINKYS_ESCAPE_H);
                if (pPlayer->GetQuestStatus(QUEST_STINKYS_ESCAPE_A))
                    pPlayer->FailQuest(QUEST_STINKYS_ESCAPE_A);
            }
        }

        void UpdateAI(const uint32 uiDiff) {
            npc_escortAI::UpdateAI(uiDiff);

            if (!UpdateVictim())
                return;

            DoMeleeAttackIfReady();
        }
    };
};

void AddSC_dustwallow_marsh() {
    new mobs_risen_husk_spirit();
    new npc_restless_apparition();
    new npc_lady_jaina_proudmoore();
    new npc_nat_pagle();
    new npc_private_hendel();
    new npc_zelfrax();
    new npc_stinky();
    new npc_theramore_guard();
    new npc_deserter_agitator();
}
